package com.project.base.common;

import org.apache.log4j.Logger;

import java.util.*;


/**
 * @author yuanchi
 * @ClassName: ConfigManager
 * @Description: TODO 参数配置管理类
 * @date 2017年2月8日 下午2:19:07
 */
public class ConfigManager {
    Logger logger = Logger.getLogger(ConfigManager.class);

    private static ConfigManager configManager;

    /**
     * 配置项的容器.
     */
    private Map<String, BasePair<List<Config>, String[]>> paramMap = new HashMap<String, BasePair<List<Config>, String[]>>();

    /**
     * 配置索引
     */
    private Map<String, TreeSet<String>> idx_configname = new HashMap<String, TreeSet<String>>();

    private ConfigManager() {
        init();

    }

    public static synchronized ConfigManager getInstance() {
        if (configManager == null) {
            configManager = new ConfigManager();
        }
        return configManager;
    }

    public void reload() {
        init();
    }

    private void init() {
        logger.info("加载参数开始！");
        Map<String, BasePair<List<Config>, String[]>> tmpMap = new HashMap<String, BasePair<List<Config>, String[]>>();
        Map<String, TreeSet<String>> tmp_idx_configname = new HashMap<String, TreeSet<String>>();

        Map<String, String> param = new HashMap<String, String>();
        String syscode = System.getProperties().getProperty("SYSCODE");
        syscode = StringTools.isValid(syscode) ? syscode : "PUBLIC";
        param.put("syscode", syscode);
//		if (configService == null)
//		{
//			configService = (ConfigService) SpringContextUtil.getBean(ConfigService.class);
//		}
//		List<Config> list=configService.queryConfig(param);
        List<Config> list = new ArrayList<>();
        int configCount = 0;
        String lastSysCode = null;
        String key = null;
        String lastKey = null;
        List<Config> valueList = new ArrayList<Config>();
        TreeSet<String> nameSet = null;
        ;
        BasePair<List<Config>, String[]> bp = null;
        String[] strs = null;
        Config invo = null;
        for (Config vo : list) {
            key = vo.getConfigname() + "|" + vo.getParamname();//存储方式的缘故,ConfigName中不能出现"|"
            if (vo.getParamvalue() == null) vo.setParamvalue("");//特殊处理,谨防空指针
            if (lastKey == null) {
                valueList.add(vo);
                lastSysCode = vo.getSyscode();
            } else if (lastKey.equals(key)) {
                if (StringTools.equals(vo.getSyscode(), lastSysCode)) {
                    addStrListPlus(valueList, vo);
                } else if (!"PUBLIC".equals(vo.getSyscode())) {
                    valueList.clear();
                    addStrListPlus(valueList, vo);
                    lastSysCode = vo.getSyscode();
                }
            } else {
                strs = new String[valueList.size()];
                for (int i = 0; i < valueList.size(); i++) {
                    invo = valueList.get(i);
                    strs[i] = invo.getParamvalue();
                    if ((nameSet = tmp_idx_configname.get(invo.getConfigname())) != null) {
                        nameSet.add(invo.getParamname());
                    } else {
                        nameSet = new TreeSet<String>(new AlphaComp());
                        nameSet.add(invo.getParamname());
                        tmp_idx_configname.put(invo.getConfigname(), nameSet);
                    }
                }
                bp = new BasePair<List<Config>, String[]>(valueList, strs);
                tmpMap.put(lastKey, bp);
                configCount += valueList.size();
                valueList = new ArrayList<Config>();
                addStrListPlus(valueList, vo);
                lastSysCode = vo.getSyscode();
            }
            lastKey = key;
        }
        if (valueList.size() > 0) {
            strs = new String[valueList.size()];
            for (int i = 0; i < valueList.size(); i++) {
                invo = valueList.get(i);
                strs[i] = invo.getParamvalue();
                if ((nameSet = tmp_idx_configname.get(invo.getConfigname())) != null) {
                    nameSet.add(invo.getParamname());
                } else {
                    nameSet = new TreeSet<String>(new AlphaComp());
                    nameSet.add(invo.getParamname());
                    tmp_idx_configname.put(invo.getConfigname(), nameSet);
                }
            }
            bp = new BasePair<List<Config>, String[]>(valueList, strs);
            tmpMap.put(lastKey, bp);
            configCount += valueList.size();
        }
        paramMap = tmpMap;
        idx_configname = tmp_idx_configname;
        logger.info("加载参数结束！加载参数条数：" + configCount);

    }

    /**
     * 将字符串加入到list
     *
     * @param list List
     * @param
     * @return boolean, add时true, join时false
     */
    private boolean addStrListPlus(List<Config> list, Config vo) {
        StringBuffer sb = new StringBuffer();
        boolean isAdd = true;

        if (list == null) {
            isAdd = false;
        } else if (list.size() == 0) {
            list.add(vo);
        } else {
            Config lastVo = list.get(list.size() - 1);
            String str = vo.getParamvalue();
            String lastStr = lastVo.getParamvalue();
            if (lastStr != null && str != null && lastStr.endsWith("-->") && str.startsWith("<--")) {
                sb.append(lastStr).append(str).delete(lastStr.length() - 3, lastStr.length() + 3);
                lastVo.setParamvalue(sb.toString());
                sb.delete(0, sb.length());
                isAdd = false;
            } else {
                list.add(vo);
            }
        }
        return isAdd;
    }

    public class AlphaComp implements Comparator<String> {

        public int compare(String s1, String s2) {
            s1 = s1.toLowerCase();
            s2 = s2.toLowerCase();
            return s1.compareTo(s2);
        }

    }

    /**
     * 此方法放回由configName和paramName确定的配置项参数的第一个值
     * 注意如果配置项配置了多个参数,返回第一个值.
     *
     * @param configName 配置项名字
     * @param paramName  配置项的参数名
     * @return 返回的配置参数的值.如果查找相应的失败返回""
     */
    public String getParamValue(String configName, String paramName) {
        Map<String, BasePair<List<Config>, String[]>> tmpMap = paramMap;
        BasePair<List<Config>, String[]> bp = tmpMap.get(configName + "|" + paramName);
        if (bp == null || bp.getValue2().length == 0) {
            return "";
        }
        return bp.getValue2()[0];
    }

    /**
     * 此方法放回由configName和paramName确定的配置项参数的第一个值
     * 注意如果配置项配置了多个参数,返回第一个值.如果没有配置则返回默认值
     *
     * @param configName 配置项名字
     * @param paramName  配置项的参数名
     * @param defalt     默认值
     * @return
     */
    public String getParamValue(String configName, String paramName, String defalt) {
        return StringTools.nvl(getParamValue(configName, paramName), defalt);
    }

    /**
     * 此方法放回由configName和paramName确定的配置项参数的第一个ConfigVo
     *
     * @param configName 配置项名字
     * @param paramName  配置项的参数名
     * @return
     */
    public Config getConfigVo(String configName, String paramName) {
        Map<String, BasePair<List<Config>, String[]>> tmpMap = paramMap;
        BasePair<List<Config>, String[]> bp = tmpMap.get(configName + "|" + paramName);
        if (bp == null || bp.getValue1().size() == 0) {
            return null;
        }
        return bp.getValue1().get(0);
    }

    /**
     * 此方法放回由configName和paramName确定的配置项参数的所有值
     *
     * @param configName 配置项名字
     * @param paramName  配置项的参数名
     * @return String[] 返回配置参数的所有值,如果查询失败则返回0长度的String[]
     */
    public String[] getParamValues(String configName, String paramName) {
        Map<String, BasePair<List<Config>, String[]>> tmpMap = paramMap;
        BasePair<List<Config>, String[]> bp = tmpMap.get(configName + "|" + paramName);
        if (bp == null) {
            return new String[0];
        } else {
            return bp.getValue2();
        }
    }

    /**
     * 此方法放回由configName和paramName确定的配置项参数的所有ConfigVo
     *
     * @param configName 配置项名字
     * @param paramName  配置项的参数名
     * @return
     */
    public List<Config> getConfigVoList(String configName, String paramName) {
        Map<String, BasePair<List<Config>, String[]>> tmpMap = paramMap;
        BasePair<List<Config>, String[]> bp = tmpMap.get(configName + "|" + paramName);
        if (bp == null) {
            return null;
        }
        return bp.getValue1();
    }

    /**
     * 返回指定配置项的所有配置参数名
     *
     * @param configName 配置项
     * @return 有配置参数名，如果查询失败则返回0长度的String[]
     */
    public String[] getParamNamesByConfigName(String configName) {
        Map<String, TreeSet<String>> tmpMap = idx_configname;
        TreeSet<String> set = tmpMap.get(configName);
        if (set == null) {
            return new String[0];
        } else {
            return set.toArray(new String[0]);
        }
    }

    /**
     * 返回指定配置项的所有配置参数值
     *
     * @param configName 配置项
     * @return 有配置参数值, 如果查询失败则返回0长度的String[][]
     */
    public String[][] getParamValuesByConfigName(String configName) {
        Map<String, BasePair<List<Config>, String[]>> tmpMap = paramMap;
        String[] strs = getParamNamesByConfigName(configName);
        String[][] rtnValues = new String[strs.length][0];
        BasePair<List<Config>, String[]> bp = null;
        for (int i = 0; i < strs.length; i++) {
            if ((bp = tmpMap.get(configName + "|" + strs[i])) != null) {
                rtnValues[i] = bp.getValue2();
            }
        }
        return rtnValues;
    }

    /**
     * 打印所有的参数配置项信息
     *
     * @return String 配置信息字符串
     */
    public String showAllParams() {
        Map<String, BasePair<List<Config>, String[]>> tmpMap = paramMap;
        Set<String> keySet = tmpMap.keySet();
        Iterator<String> it = keySet.iterator();
        StringBuffer sb = new StringBuffer();
        String key = null;
        String[] paramValues = null;

        while (it.hasNext()) {
            key = (String) it.next();
            paramValues = (String[]) tmpMap.get(key).getValue2();
            sb.append(key).append("=");
            for (int i = 0; i < paramValues.length; i++) {
                sb.append("<").append(paramValues[i]).append(">");
            }
            if (it.hasNext()) sb.append("\n");
        }
        return sb.toString();
    }


    /**
     * 此方法放回由configName和paramName确定的配置项参数的第一个值
     * 注意如果配置项配置了多个参数,返回第一个值.
     *
     * @param configName 配置项名字
     * @param paramName  配置项的参数名
     * @return 返回的配置参数的值.如果查找相应的失败返回"".
     */
    public static String getParamValueDirect(String configName, String paramName) {
        return getInstance().getParamValue(configName, paramName);
    }

    /**
     * 此方法放回由configName和paramName确定的配置项参数的第一个值
     * 注意如果配置项配置了多个参数,返回第一个值.如果没有配置则返回默认值
     *
     * @param configName 配置项名字
     * @param paramName  配置项的参数名
     * @param defalt     默认值
     * @return
     */
    public static String getParamValueDirect(String configName, String paramName, String defalt) {
        return getInstance().getParamValue(configName, paramName, defalt);
    }

}
